package peace.htmllooker.node.form
{
import flash.display.DisplayObject;
import flash.events.Event;
import flash.text.StyleSheet;

import peace.gui.controls.Control;
import peace.gui.controls.GroupSelection;
import peace.gui.controls.SelectEvent;
import peace.gui.controls.buttons.Checkbox;
import peace.gui.controls.buttons.PushButton;
import peace.gui.controls.list.ComboBox;
import peace.gui.controls.list.ListBox;
import peace.gui.controls.text.InputField;
import peace.gui.controls.RubberSprite;
import peace.htmllooker.Box;
import peace.htmllooker.Htmllooker;
import peace.htmllooker.Node;
/**
 * Поле формы
 */
public class FormField extends Node
{
	public static const TEXT:String = "text";
	public static const PASSWORD:String = "password";
	public static const SUBMIT:String = "submit";
	public static const CHECKBOX:String = "checkbox";
	public static const RADIO:String = "radio";
	public static const HIDDEN:String = "hidden";
	public static const SELECT:String = "select";
	public static const TEXTAREA:String = "textarea";
	/**
	 * 
	 */
	public var type:String;
	/**
	 * 
	 */
	public var id:String;
	/**
	 * 
	 */
	public var control:Control;
	/**
	 * значение аттрибута value для контрола
	 */
	public var data:String;
	/**
	 * массив значений для SELECT-типа 
	 */	
	protected var selectData:Array;
	/**
	 * 
	 * @param xml
	 * @param css
	 * 
	 */	
	public function FormField(xml:XML, css:StyleSheet)
	{
		super(xml, css);
	}
	
	override protected function init(xml:XML, css:StyleSheet):void
	{
		// выставляем паддинг
		padding.topBottom = padding.leftRight = 2;
		
		// разбираем xml
		id = xml.@name;

		switch (xml.localName())
		{
			case "select":
			case "textarea":
			{
				type = xml.localName();
				break;
			}
			default:
			{
				type = xml.@type;
			}
		}
		
		if (xml.@value != undefined)
		{
			data = xml.@value; 
		}
		
		// хуярим контролы
		switch (type)
		{
			case HIDDEN:
			{
				// добавляем фейковый пустой контрол
				// ибо хидден-поле должно работать аналогично остальным
				control = new RubberSprite();
				break;
			}
			
			case CHECKBOX:
			{
				// Checkbox
				control = new Htmllooker.formControlClasses.checkbox ();
				Checkbox (control).label.htmlText = xml.*.toXMLString();
				if (xml.@checked != undefined)
				{
					Checkbox (control).selected = true;
				}
				
				break;
			}
			
			case RADIO:
			{
				// Checkbox
				control = new Htmllooker.formControlClasses.radio ()
				Checkbox (control).label.htmlText = xml.*.toXMLString();
				if (xml.@checked != undefined)
				{
					control.selected = true;
				}
				
				addEventListener(Event.ADDED_TO_STAGE, onAddedToStage, false,0,true);
				
				break;
			}
			
			case SUBMIT:
			{
				// PushButton
				control = new Htmllooker.formControlClasses.button ();
				var b:PushButton = PushButton (control);
				if (data)
				{
					b.value = data;
					if (b.width < b.getIcon().width)
					{
						b.width = b.getIcon().width + 6;
					}
				}
				control.addEventListener (SelectEvent.CHANGE, onSubmit, false,0,true);
				
				break;
			}
			
			case PASSWORD:
			case TEXT:
			{
				// InputField
				control = new Htmllooker.formControlClasses.input ();

				var t:InputField = InputField(control);
				t.password = type == PASSWORD;
				if (data) t.text = data;
				
				break;
			}
			
			case TEXTAREA:
			{
				// InputField
				control = new Htmllooker.formControlClasses.input (null, true);
				
				if (xml.@rows != undefined)
				{
					control.height = parseInt(xml.@rows) * 22;
				}
				
				data = xml.text();
				InputField(control).text = data;
				
				break;
			}
			case SELECT:
			{
				var size:Number;
				var multiple:Boolean = false;
				if (xml.@size != undefined) size = parseInt(xml.@size);
				if (xml.@multiple != undefined) multiple = true;
				
				// вытаскиваем значения
				var node:XML;
				var label:String;
				var labels:Array = [];
				var beginValue:Array = [];
				selectData = [];
				for each (node in xml.*)
				{
					selectData.push (String(node.@value));	
					label = node.*.toXMLString();
					if (node.@selected != undefined)
					{
						beginValue.push (label)
					}
					labels.push (label);					
				}
				
				var list:ListBox;
				if (multiple || size && size > 1)
				{
					list = new Htmllooker.formControlClasses.list (labels, multiple);
					control = list;
				}
				else
				{
					list = new Htmllooker.formControlClasses.list (labels, false);
					control = new Htmllooker.formControlClasses.combo (list);
				}
				
				if (size)
				{
					control.height = 20 * size;
				}
				
				// присваиваем начальное значение
				control.value = beginValue;
				
				break;
			}
		}
		
		if (control)
		{
			if (type != HIDDEN)
			{
				addChild(control);
			}
			
			minWidth = preferredWidth = control.width + shellWidth;
			minHeight = preferredHeight = control.height + shellHeight;
		}
		
		super.init(xml,css);
		
	}
	/**
	 * Возвращаем значение для всех типов контролов. <br>
	 * Если текущее значение контрола не нуждается в отправке на сервер - возвращает null.
	 * 
	 * @return 
	 * 
	 */	
	public function get value ():String
	{
		if (type == HIDDEN)
		{
			return data;
		}
		else if (type == CHECKBOX || type == RADIO)
		{
			return control.selected ? data : null;
		}
		else if (type == TEXT || type == TEXTAREA)
		{
			return control.value == "" ? null : control.value;
		}
		else if (type == SELECT)
		{
			var arr:Array;
			var i:int;
			// собираем значение в виде индексов
			if (control is ComboBox)
			{
				i = ComboBox(control).selectedIndex;
				arr = i > -1 ? [i] : [];
			}
			else
			{
				arr = ListBox (control).selectedIndexes;
			}
			
			if (arr.length == 0) return null;
			
			// меняем индексы на значения данных селекта
			for (i = 0; i < arr.length; i++)
			{
				arr[i] = selectData [arr[i]];
			}
			
			var result:String = arr.join(","); 
			return result == "" ? null : result;
		}
		
		return null;
	}
	/**
	 * На всякий случай
	 * 
	 * @param s
	 * 
	 */	
	public function set value (s:String):void
	{
		if (type == SELECT)
		{
			var values:Array = s ? s.split(",") : [];
			var indexes:Array = [];
			var v:String;
			for each (v in values)
			{
				indexes.push (selectData.indexOf(v));
			}
			
			if (control is ListBox)
			{
				ListBox(control).selectedIndexes = indexes;
			}
			else if (control is ComboBox)
			{
				ComboBox(control).selectedIndex = indexes[0];
			}
		}
		else
		{
			data = control.value = s;
		}
	}
	/**
	 * 
	 * @return родительскую форму 
	 * 
	 */	
	protected function get form ():Form
	{
		var box:Box = parentBox;
		for (; !(box is Form); box = box.parentBox) {}
		return Form(box);
	}
	
	override public function get content():DisplayObject
	{
		return control;
	}
	/**
	 * 
	 * @param e
	 * 
	 */	
	private function onSubmit (e:SelectEvent):void
	{
		form.submit();
	}
	/**
	 * Для радиокнопки нужно добавляться в Form::radiogroups <br>
	 * Что возможно после добавления в дисплей-лист формы
	 * 
	 * @param e
	 * 
	 */	
	private function onAddedToStage (e:Event):void
	{
		if (type == RADIO)
		{
			var f:Form = form;
			var g:GroupSelection
			if (f.radiogroups[id])
			{
				g = GroupSelection(f.radiogroups[id]);
			}
			else
			{
				g = new GroupSelection(null, false, true);
				f.radiogroups[id] = g;
			}
			g.add(control);
		}
	}
	
}
}
